<?php

namespace app\admin\model;

use think\exception\DbException;
use think\facade\Config;
use think\facade\Session;
use think\model\concern\SoftDelete;
use think\Model;

class User extends Model
{
    use SoftDelete;
    protected $table = 'user';
    protected $insert = [
        'create_user',
        'update_user',
        'status' => 1,
    ];
    protected $update = [
        'update_user',
    ];

    public function setCreateUserAttr()
    {
        return Session::get(Config::get('user_session_key'))['id']??1;
    }

    public function setUpdateUserAttr()
    {
        return Session::get(Config::get('user_session_key'))['id']??1;
    }

    /**
     * 用户登录验证
     * @param string $username
     * @param string $password
     * @param bool $remember
     * @return bool
     * @throws DbException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function login($username = '', $password = '', $remember = false)
    {
        $username = trim($username);
        $password = trim($password);
        //验证用户
        $user = self::where('username', $username)->where('status', 1)->find();
        if ($user == null) {
            $this->log(['username' => $username, 'remark' => '用户不存在，或被禁用']);
            return false;
        };
        // 密码校验
        if ($user->password != md5(md5($password) . $user->salt)) {
            $this->log(['username' => $username, 'remark' => '密码错误']);
            return false;
        };
        //写入登录日志
        $this->log(['username' => $username, 'remark' => '登录成功']);
        // 缓存登录信息
        $data = [
            'id' => $user->id,
            'username' => $user->username,
            'nickname' => $user->nickname,
        ];
        Session::set(Config::get('user_session_key'), $data);
        Session::set(Config::get('user_session_sign'), $this->dataSign($data));
        //缓存权限
        $permissions = $this->permissions($user->id);
        Session::set(Config::get('user_permission_key'), $permissions);
        return true;
    }

    /**
     * 写入登录日志
     * @param $data
     * @return bool
     */
    public function log($data)
    {
        try {
            LoginLog::create($data);
            return true;
        } catch (DbException $exception) {
            return false;
        }
    }

    /**
     * 判断是否登录
     * @return bool|array
     */
    public function isLogin()
    {
        $user = Session::get(Config::get('user_session_key'));
        if (isset($user['id'])) {
            return Session::get(Config::get('user_session_sign')) == $this->dataSign($user) ? true : false;
        }
        return false;
    }

    /**
     * 退出登陆
     * @return bool
     */
    public function logout()
    {
        Session::delete(Config::get('user_session_key'));
        Session::delete(Config::get('user_session_sign'));
        Session::delete(Config::get('user_permission_key'));
        return true;
    }

    /**
     * 数据签名认证
     * @param array $data 被认证的数据
     * @return string 签名
     */
    public function dataSign($data = [])
    {
        if (!is_array($data)) {
            $data = (array)$data;
        }
        ksort($data);
        $code = http_build_query($data);
        $sign = sha1($code);
        return $sign;
    }

    /**
     * 用户拥有的角色
     * @return \think\model\relation\BelongsToMany
     */
    public function roles()
    {
        return $this->belongsToMany('app\admin\model\Role', 'user_role', 'role_id', 'user_id');
    }

    /**
     * 用户的直接权限
     * @return \think\model\relation\BelongsToMany
     */
    public function directPermissions()
    {
        return $this->belongsToMany('app\admin\model\Permission', 'user_permission', 'permission_id', 'user_id');
    }

    /**
     * 用户的所有权限
     * @param $id
     * @return array
     * @throws DbException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function permissions($id)
    {
        $user = self::with(['roles.permissions', 'directPermissions'])->findOrEmpty($id);
        $permissions = [];
        //超级管理员缓存所有权限
        if ($user['id'] == Config::get('root_id')){
            $perms = Permission::order('sort','asc')->select();
            foreach ($perms as $p){
                $permissions[$p['id']] = [
                    'id' => $p['id'],
                    'name' => $p['name'],
                    'description' => $p['description'],
                    'type' => $p['type'],
                    'parent_id' => $p['parent_id'],
                    'url' => $p['url'],
                    'icon' => $p['icon'],
                    'sort' => $p['sort'],
                ];
            }
        }else{
            //处理角色权限
            if (isset($user['roles']) && !empty($user['roles'])) {
                foreach ($user['roles'] as $r) {
                    if (isset($r['permissions']) && !empty($r['permissions'])) {
                        foreach ($r['permissions'] as $p) {
                            $permissions[$p['id']] = [
                                'id' => $p['id'],
                                'name' => $p['name'],
                                'description' => $p['description'],
                                'type' => $p['type'],
                                'parent_id' => $p['parent_id'],
                                'url' => $p['url'],
                                'icon' => $p['icon'],
                                'sort' => $p['sort'],
                            ];
                        }
                    }
                }
            }
            //处理直接权限
            if (isset($user->direct_permissions) && !$user->direct_permissions->isEmpty()) {
                foreach ($user->direct_permissions as $p) {
                    $permissions[$p['id']] = [
                        'id' => $p['id'],
                        'name' => $p['name'],
                        'description' => $p['description'],
                        'type' => $p['type'],
                        'parent_id' => $p['parent_id'],
                        'url' => $p['url'],
                        'icon' => $p['icon'],
                        'sort' => $p['sort'],
                    ];
                }
            }
        }
        //合并权限为用户的最终权限
        return $permissions;
    }

}